﻿#include "file_manager.h"
#include "serial_file_com_nonebuf.h"
#include "rec_write_avi.h"
#ifndef _WIN32
#include <sys/statvfs.h>
#include "dirent.h"
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#endif
#ifdef _SIMULATE_RECORD_
#include "MultiCHData.h"
#endif
CFile_manager::CFile_manager()
{
#ifdef _SIMULATE_RECORD_
	m_recFileSize = SIZE_MB(8);  //模拟录像打包大小
#else
	m_recFileSize = SIZE_MB(256);
#endif
	m_recordSN        = 0;
	m_norDir_percent  = 70;
	m_pFile           = NULL;
	m_total_space_MB  = 0;
	m_cycleFileSize   = 0;
	m_diskIndex       = 0;
}

CFile_manager::~CFile_manager()
{

}

int CFile_manager::Init(char * storageName,int chNum,RECORD_DIR_INFO_S recDir)
{
	int  ret = 0;
	char mntDir[60] = {0};
    TRACE("File_manager init storageName %s chNum %d  \n",storageName,chNum);
	if( NULL == storageName)
	{
        TRACE(" Error storage name %s.\n",storageName);
		return ERR_EMPTY_POINT;
	}

	if( 0 != access(storageName,0) )
	{
		TRACE("device %s  not found .\n",storageName);
		return ERR_NO_DEVICE;
	}

	strcpy(m_dev,storageName);

	//获取设备挂载路径
	GetMountPath(mntDir,storageName);
    TRACE("GetMountPath  mntDir %s storageName %s .\n",mntDir,storageName);
	if( 0 == strlen(mntDir))
	{
		//没有正常挂载

		//执行rf挂载操作
		char  cmd_mnt[80] = {0};
		sprintf(cmd_mnt,"mount %sp1 %s",storageName,recDir.df_mntPath);;
#ifndef _WIN32
		system(cmd_mnt);
#endif
		TRACE("Device %sp1 not mounted.\n",storageName,recDir.df_mntPath);
		strcpy(mntDir,recDir.df_mntPath);
	}
    TRACE("Init dev %s  OK  mntDir %s .\n",storageName,mntDir);
	int dir_len = strlen(mntDir);
	char dir_flg = 0;

#ifdef _WIN32
	dir_flg = '\\';

#else
	dir_flg = '/';

#endif

	if(mntDir[dir_len-1] != dir_flg)
	{
		mntDir[dir_len]= dir_flg;
		mntDir[dir_len+1]= 0;
	}

	m_fCreater.Init(mntDir,recDir.norDir,recDir.evtDir,recDir.capture,recDir.thumbnailDir,recDir.separtor,recDir.fbox_fmt,chNum);

	//查找AVI文件
	char nor_path[240];
	char file_ext[6];

	sprintf(nor_path,"%s%s",mntDir,recDir.norDir);

	vector<string> vec_recFile;
	m_fCreater.GetFileNameExt(file_ext);
	ret = FindRecordFile(nor_path,file_ext,vec_recFile);
	//生成AVI文件信息列表
	m_map_fileInfo.clear();
	AnalysisFileList(vec_recFile);

	GetDiskInfo();
	//检查列表最后三个文件，看是否有正常关闭文件
#ifdef _SIMULATE_RECORD_
	//RepairRecord();
#endif
	return ret;
}

int CFile_manager::CreateRecordInfo(const char* storage_path,uint32_t recblk_sz,uint32_t indexInfoSize, int indexNum)
{
	int ret = 0;
	ST_INDEX_FILE_INFO hdInfo;
	char idxMagic[8]    = STFS_INDEX_MAGIC;
	uchar_t * clearBuf  = NULL;
	int headInfoLen     = sizeof(ST_INDEX_FILE_INFO);
	char index_name[60] = {0};
	char file_path[50] = {0};
	//参数检查
	if(storage_path == NULL)
	{
		ret = ERR_NO_DEVICE;
		return ERR_NO_DEVICE;
	}
	if(-1 == access(storage_path,0))
	{
		return  ret = ERR_NO_DEVICE;;
	}
	if((0 == recblk_sz)||(0 == indexInfoSize)||(0 == indexNum) )
	{
		ret = ERR_DATA_SIZE;
		return ERR_DATA_SIZE;
	}

	CSerialFileComNobuf file;

	//初始索引信息
	memset(&hdInfo,0,headInfoLen);
	memcpy(hdInfo.idxMagic,idxMagic,8);
	hdInfo.version         = STFS_INDEX_VERSION;

	hdInfo.diskInfoOffset  = INDEX_DISK_INFO_OFFSET;
	hdInfo.diskInfoLen     = INDEX_DISK_INFO_LEN;
	hdInfo.recFileSize     = recblk_sz;
	hdInfo.indexInfoOffset = INDEX_INFO_OFFSET;
	hdInfo.indexLength     = indexInfoSize;
	hdInfo.indexInfoNum    = indexNum;

	hdInfo.recInfoOffset   = INDEX_BASEINFO_OFFSET;
	hdInfo.recInfoLen	    = sizeof(REC_SEGMENT_S);			//每条文件记录的长度（用于兼容不同地结构体）
	hdInfo.recInfoNum      = (indexInfoSize - INDEX_BASEINFO_OFFSET)/hdInfo.recInfoLen;
	hdInfo.baseRecFileLBA  = 0x1000;
	hdInfo.fileSize		   = INDEX_INFO_OFFSET +  indexInfoSize * indexNum ;
	//hdInfo.checkSum		= crc32((uchar_t*)&hdInfo,headInfoLen-4);


	//增加通道数支持，以备后续支持PC端播放器，检测出当前硬盘是录过几个通道的。
	hdInfo.sptMaxCH        = 2;

	time((time_t*)&hdInfo.createTm);

	TRACE_ERR("Stroage: Index offset %d, Index file size %d \n",hdInfo.indexInfoOffset,hdInfo.fileSize);

	//清理后面的数据
	int bufSize = SIZE_1MB;
	clearBuf = new uchar_t[bufSize];
	memset(clearBuf,0,bufSize);

	uint32_t writeSize = hdInfo.fileSize - INDEX_INFO_OFFSET;
	uint32_t ioSize    = bufSize;
	uint32_t offset    = hdInfo.indexInfoOffset;

	ret = file.Seek(offset,SCSI_SEEK_SET);
	//清空索引区的数据
	while(writeSize != 0)
	{
		ioSize = ((writeSize >(uint32_t) bufSize) ? bufSize:writeSize);
		ret = file.Write(clearBuf,ioSize);
		if(ret < 0)
		{
			TRACE_ERR("Stroage:ERR Index %s Index offset %d, Index file size %d \n",storage_path,hdInfo.indexInfoOffset,hdInfo.fileSize);
			goto ERR_OUT;
		}

		writeSize -= ioSize ;
	}

	if(clearBuf)
	{
		delete [] clearBuf;
	}
	//写入文件头
	ret = file.WritePos(0,(uchar_t *)&hdInfo,headInfoLen);
	if(ret < 0)
	{
		TRACE_ERR("Write head info fail.\n");
		file.Close();
		if(clearBuf)
		{
			delete [] clearBuf;
		}
		return ret;
	}
	TRACE_ERR("Stroage:Create com index file OK. \n");
	file.Close();
	TRACE_ERR("Close index file OK. \n");
	return 0;

ERR_OUT:
	if(clearBuf)
	{
		delete [] clearBuf;
	}
	TRACE_ERR("Stroage:create %s com index file fail.\n",index_name);
	file.Close();
	return ret;
}

int CFile_manager::GetNexRecordFile(int channel,string & fileName, uint32_t & fileIndex, uint32_t & fileSize,time_t recTm,int recType)
{
	int ret = 0;
	char  file_name[80] = {0};
	int fileDirType = 0;
	//正常磁盘未满的时候获取下一个录像文件
	if(recType == RECORD_IOALARM)
	{
		fileDirType = F_EVT_REC;
	}
	else
	{
		fileDirType = F_NOR_REC;
	}

    m_fCreater.GetFilePath(file_name,fileDirType,recTm,channel);

	fileName = file_name;
	fileSize = m_recFileSize;
	return ret;
}

int CFile_manager::CreateNewFile(string & fileName,time_t curTime,int fileType)
{
	int ret = 0;

	return ret;
}

int CFile_manager::RecordStart(REC_FILE_INFO & recInfo)
{
	int ret = 0;
	MAP_RECFILE_INFO::iterator it ;
	RECFILE_INFO  fInfo;
	uint32_t key = 0;

	fInfo.status  = recInfo.status;
	fInfo.channel = recInfo.channel;
	fInfo.tmStartSec = recInfo.tmStart /1000;
	fInfo.tmEndSec   = recInfo.tmEnd / 1000;
	fInfo.length  = 0;

	key = fInfo.tmStartSec;
	fInfo.fileType = recInfo.recordType;
	m_map_fileInfo.insert(MAP_RECFILE_INFO::value_type(key,fInfo));
	recInfo.recordSN = CreateNextRecordSN();

	return ret;
}

//停止录像
int CFile_manager::RecordEnd(REC_FILE_INFO & recInfo)
{
	int ret = 0;
	MAP_RECFILE_INFO::iterator it ;
	uint32_t key = recInfo.tmStart/1000;

	it = m_map_fileInfo.find(key);
	if(it != m_map_fileInfo.end())
	{
		it->second.tmEndSec = recInfo.tmEnd /1000;
		it->second.length = recInfo.length;
		it->second.status = recInfo.status;

	}

	return ret;
}

//////////////////////////////////////////////////////////////////////////
void CFile_manager::AddToFileList(list<REC_FILE_INFO> & list, REC_FILE_INFO & index,uint32_t maxNum, uint32_t orderType)
{
	bool bSameRecord = false;
	if (0 == orderType)
	{
		if (0 == list.size())
		{
			list.push_front(index);
		}
		else if (index.tmStart <=list.begin()->tmStart)
		{
			list.push_front(index);
		}
		else if (index.tmStart >= list.back().tmStart)
		{
			if( (index.tmStart == list.back().tmStart) &&
				(index.tmEnd == list.back().tmEnd))
			{
				//
				TRACE("No need add this record file.\n");
				return;
			}
			list.push_back(index);
		}
		else
		{
			std::list<REC_FILE_INFO>::iterator itHead = list.begin();
			std::list<REC_FILE_INFO>::iterator it = itHead;

			long h=0, t=0, i=0, m=0, num = 0;
			t = (int)(list.size()-1);
			while (h+1 < t)
			{
				it = itHead;
				m = ((h + t) >> 1);

				i = 0;
				num = m - h;
				while (i < num)
				{
					++ it;
					++ i;
				}

				if ((*it).tmStart < index.tmStart)
				{
					itHead = it;
					h = m;
				}
				else if ((*it).tmStart == index.tmStart)
				{
					break;
				}
				else
				{
					t = m;
				}
			}

			bSameRecord = ((*it).tmStart == index.tmStart) && ((*it).tmEnd == index.tmEnd);

			if(!bSameRecord)
			{
				if ((*it).tmStart >= index.tmStart)
				{
					list.insert(it, index);
				}
				else
				{
					list.insert(++it, index);
				}
			}
		}
	}
	else
	{
		if (0 == list.size())
		{
			list.push_front(index);
		}
		else if (index.tmStart >=list.begin()->tmStart)
		{
			list.push_front(index);
		}
		else if (index.tmStart <= list.back().tmStart)
		{
			if( (index.tmStart == list.back().tmStart) &&
				(index.tmEnd == list.back().tmEnd))
			{
				//
				TRACE("No need add this record file.\n");
				return;
			}
			list.push_back(index);
		}
		else
		{
			std::list<REC_FILE_INFO>::iterator itHead = list.begin();
			std::list<REC_FILE_INFO>::iterator it = itHead;

			long h=0, t=0, i=0, m=0, num = 0;
			t = (int)(list.size()-1);
			while (h+1 < t)
			{
				it = itHead;
				m = ((h + t) >> 1);

				i = 0;
				num = m - h;
				while (i < num)
				{
					++ it;
					++ i;
				}

				if (index.tmStart < (*it).tmStart)
				{
					h = m;
					itHead = it;
				}
				else if (index.tmStart == (*it).tmStart)
				{
					h = m-1;
					t = m;
				}
				else
				{
					t = m;
				}
			}

			CROSS_ASSERT(h+1 == t);
			bSameRecord = ((*it).tmStart == index.tmStart) && ((*it).tmEnd == index.tmEnd);

			if(!bSameRecord)
			{
				if(index.tmStart < (*it).tmStart)
				{
					list.insert(++ it, index);
				}
				else
				{
					if(index.tmEnd != it->tmEnd)
					{
						list.insert(it, index);
					}
				}
			}
		}
	}

	if ((maxNum > 0) && (list.size() > maxNum))
	{
		//当发现元素的个数，大于总大小于弹出最后一个元素
		list.pop_back();
	}
}

int CFile_manager::SearchFile(int64_t tmStart, int64_t tmEnd,int recType, vector<uint8_t>& vecCH,uint32_t maxNum,MAP_CH_FILE_T& mapPerChFile,bool bForward)
{
	int ret = 0;
	MAP_CH_FILE_T::iterator itPerCH;;
	REC_FILE_INFO		    fileInfoEx;
	int channel = 0;
	int i = 0;
	int info_cnt = m_map_fileInfo.size();
	int file_cnt = 0;
	RECFILE_INFO * pInfo = NULL;

	map<uint32_t,RECFILE_INFO>::iterator itRec;

	for(itRec = m_map_fileInfo.begin(); itRec != m_map_fileInfo.end(); itRec++)
	{
		pInfo   = &itRec->second;
		channel = pInfo->channel;
		if(vecCH[channel] != 1)
		{
			continue;
		}

		itPerCH = mapPerChFile.find(channel);
		if (itPerCH == mapPerChFile.end())
		{
			REC_FILE_LIST pList;
			mapPerChFile.insert(std::map<uint32_t, REC_FILE_LIST>::value_type(channel, pList));
			itPerCH = mapPerChFile.find(channel);
		}
		fileInfoEx.status    = pInfo->status;
		fileInfoEx.channel   = channel;
		fileInfoEx.diskIndex = m_diskIndex;
		fileInfoEx.recordType = pInfo->fileType;
		fileInfoEx.tmStart  = pInfo->tmStartSec;
		fileInfoEx.tmEnd    = pInfo->tmEndSec;
		fileInfoEx.length   = pInfo->length;

		CFile_manager::AddToFileList(itPerCH->second, fileInfoEx,maxNum,bForward);
		file_cnt++;
	}


	return file_cnt;
}


uint32_t CFile_manager::GetCurRecordSN()
{
	return m_recordSN;
}

uint32_t CFile_manager::GetNextRecordSN()
{
	return m_recordSN +1;
}

uint32_t CFile_manager::CreateNextRecordSN()
{
	m_recordSN++;
	return m_recordSN;
}


int CFile_manager::RegisterRecWriter(int ch, CRecWriteBase * pRec)
{
	m_lock.Lock();
	m_mpRecording[ch] = pRec;
	m_lock.UnLock();
	return 0;
}

void CFile_manager::GetMaxTime(time_t & maxTm)
{

}

bool   CFile_manager:: IsDiskFull()
{
	if(GetRecFreeSpaceMB() < (BYTE_TO_MB(m_recFileSize) + 16) )
	{
		return true;
	}
	else
	{
		return false;
	}
}

uint32_t CFile_manager::GetDiskFreeSpaceMB()
{
	uint32_t  freeMB = 0;
	int64_t freeSpace  = 0;
#ifdef _WIN32
	uint64_t i64FreeByteToCaller = 0;
	uint64_t i64TotalBytes = 0;
	uint64_t i64FreeBytes = 0;

	BOOL bRet = GetDiskFreeSpaceEx(m_dev,
		(PULARGE_INTEGER)&i64FreeByteToCaller,
		(PULARGE_INTEGER)&i64TotalBytes,
		(PULARGE_INTEGER)&i64FreeBytes);
	if(!bRet)
	{
		TRACE_ERR("Cannot get disk free space.\n");
		return ERR_DATA_SIZE;
	}
	freeMB = (uint32_t)(i64FreeBytes >> 20);
#else
	uint32_t remain_spaceMB = m_total_space_MB * (100 -m_norDir_percent)/100;  //保留空间
	struct statvfs disk_statfs;
	if( statvfs(m_fCreater.GetDir_mount(), &disk_statfs) == -1 )
	{
		TRACE("get free space fail.errno %d .\n",errno);
		return 16;
	}

	freeSpace = ((long long)disk_statfs.f_bsize  * (long long)disk_statfs.f_bfree);
	freeMB    =  freeSpace>>20;
	TRACE("Free sacpe %d.\n",freeMB);
#endif
	return freeMB;
}
uint32_t CFile_manager::GetRecFreeSpaceMB()
{
	uint32_t freeSizeMB = 20;
	uint64_t freeSpace  = 0;
	uint64_t totalSpace = 0;
	uint32_t norSizeMB = m_total_space_MB * m_norDir_percent/100;
	string  norPath;
	uint32_t rec_spaceMB = 0;
	int ret = 0;
	uint64_t dirSize = 0;

	m_fCreater.GetPath(F_NOR_REC,norPath);
	if(norPath.empty())
	{
		return 0;
	}

	ret = GetFolderSize(norPath.c_str(), &dirSize);
	rec_spaceMB = (uint32_t)(dirSize >>20);

	if(rec_spaceMB < norSizeMB)
	{
		freeSizeMB = norSizeMB - rec_spaceMB;
	}
	else
	{
		freeSizeMB = 0;
	}
	return freeSizeMB;
}

int CFile_manager::GetCycleIndex(uint32_t channel,string & filename,time_t recTm,unsigned short & diskIndex, uint32_t & indexNo)
{
	int   ret = 0;
	char  old_file_name[80] = {0};
	char  new_file_name[80] = {0};
	bool  bRet  = false;
	//正常磁盘未满的时候获取下一个录像文件
	m_fCreater.GetFilePath(new_file_name,F_NOR_REC,recTm,channel);
	filename = new_file_name;
	bool bFound = false;
	uint32_t baseNorSizeMB = m_total_space_MB * m_norDir_percent/100;
	uint32_t realNorSizeMB = 0;
	uint64_t totalNorSize  = 0;
	uint32_t recFileMB     = 0;

	//找到旧的录像文件，
	if( (int )m_map_fileInfo.size() != 0)
	{
		string  norPath;
		m_fCreater.GetPath(F_NOR_REC,norPath);

		do
		{
			if(m_map_fileInfo.size() == 0)
			{
				break;
			}
			RECFILE_INFO * pRecInfo =  &(m_map_fileInfo.begin()->second);
			time_t rec_tm = pRecInfo->tmStartSec;

			m_fCreater.GetFilePath(old_file_name,F_NOR_REC,rec_tm,channel);
			
			m_map_fileInfo.erase(m_map_fileInfo.begin());

			if(0 == access(old_file_name,0))
			{
				uint32_t recSzie = get_file_sie(old_file_name);
				recFileMB = BYTE_TO_MB(recSzie);

				ret = GetFolderSize(norPath.c_str(),&totalNorSize);

				realNorSizeMB = (uint32_t)BYTE_TO_MB(totalNorSize);

				//假如减掉旧的录像文件，空间仍然比预设的空间大，就继续删除找下一个录像文件
				if(realNorSizeMB - recFileMB  > baseNorSizeMB )
				{
					bRet = DeleteFile(old_file_name);
					if(!bRet)
					{
#ifdef _WIN32
						int err = GetLastError();
						CROSS_ASSERT(0!= access(old_file_name,0));
#else
						int err =  errno;
#endif // _WIN32
						TRACE_ERR("Del old file fail old_file_name %s err %d .\n",old_file_name,err);
					}
					TRACE_ERR("record space is over default NOR percent realNorSizeMB %d MB recFileMB %d MB  baseNorSize %d MB .\n",realNorSizeMB,recFileMB,baseNorSizeMB);
					continue;
				}
				
				bFound = true;
			}
			else
			{
				continue;
			}

		} while (!bFound);

		TRACE("Get Cycle file %s  channel %d .\n",old_file_name,channel);
	}

	//情况一 文件很大，只修改文件名，在文件内部覆盖使用
	//回收的原则，尽量让当前的文件与预分配的文件大小相一致
	//1.然后修改旧的录像文件名字
	m_cycleFileSize = get_file_sie(old_file_name);
	if(m_cycleFileSize + SIZE_MB(1) > m_recFileSize)
	{
		bRet = RenameFile(old_file_name,new_file_name);
		if(!bRet)
		{
			bRet = DeleteFile(old_file_name);
			if(!bRet)
			{
#ifdef _WIN32
				int err = GetLastError();
				CROSS_ASSERT(0!= access(old_file_name,0));
#else
				int err =  errno;
#endif // _WIN32
				TRACE_ERR("Del old file fail old_file_name %s err %d .\n",old_file_name,err);
			}
			m_cycleFileSize = m_recFileSize;
		}

		return  0;
	}
	else
	{
		//情况二，文件很偏小，删除掉文件重新创建
		//2.删除掉
		bRet = DeleteFile(old_file_name);
		if(!bRet)
		{
#ifdef _WIN32
			int err = GetLastError();
#else
            int err =  errno;
#endif // _WIN32
            TRACE_ERR("Del old file fail old_file_name %s err %d .\n",old_file_name,err);
		}
		m_cycleFileSize = m_recFileSize;
	}

	//如果存在缩略图，则删除掉旧的

	return ret;
}

int CFile_manager::RepairRecord()
{
	int ret = 0;

	if(0 == m_map_fileInfo.size())
	{
		return 0;
	}

	CAviFileWrite pFile(0);

	char  file_name[128] = {0};
	map<uint32_t,RECFILE_INFO>::reverse_iterator itInfo;
	int chk_num = 3;
	int64_t startTime  = 0;
	int64_t endTime    = 0;
	uint32_t file_size = 0;
	uint32_t file_idx  = 0;
	RECFILE_INFO * pInfo = NULL;

	for(itInfo = m_map_fileInfo.rbegin(); itInfo != m_map_fileInfo.rend(); itInfo++)
	{
		//正常关闭就不用修复
		pInfo = &itInfo->second;

		startTime  = pInfo->tmStartSec;
		startTime *= STFS_1SEC_MS;

		m_fCreater.GetFilePath(file_name,F_NOR_REC, pInfo->tmStartSec,pInfo->channel);
		ret = pFile.RepairFile(file_name,0,0,m_recFileSize,startTime,file_size,endTime);

		if(--chk_num == 0)
		{
			break;
		}
	}

	return ret;
}

int CFile_manager::GetNextPic(string & picName,time_t curTm, int channel)
{
	int ret = 0;

	ret = m_fCreater.GetPicFile(picName,curTm,channel);

	return ret;
}

int CFile_manager::FindRecordFile(char * szPath,const char * file_ext,vector<string> & vec_recFile)
{
	int ret = 0;
#ifdef _WIN32
	char szFind[MAX_PATH] = {0};
	WIN32_FIND_DATA FindFileData;

	sprintf(szFind,"%s\\*.%s",szPath,file_ext);;
	HANDLE hFind=::FindFirstFile(szFind,&FindFileData);
	if(INVALID_HANDLE_VALUE == hFind)
	{
		return 0;
	}

	while(TRUE)
	{
		if(FindFileData.dwFileAttributes
			&FILE_ATTRIBUTE_ARCHIVE)
		{
			if(strstr(FindFileData.cFileName,file_ext))
			{
				vec_recFile.push_back(FindFileData.cFileName);
			}
		}
		if(!FindNextFile(hFind,&FindFileData))
			break;
	}
	FindClose(hFind);
#else
	DIR *d;
	struct dirent *file;
	struct stat sb;
	if(!(d = opendir(szPath)))
	{
		printf("error opendir %s!!!/n",szPath);
		return -1;
	}

	while((file = readdir(d)) != NULL)
	{
		/**把当前目录.，上一级目录..及隐藏文件都去掉**/
		if(strncmp(file->d_name, ".", 1) == 0)
			continue;

		if(strstr(file->d_name,file_ext))
		{
			vec_recFile.push_back(file->d_name);
		}
	}
	closedir(d);
#endif
	return ret;
}

int CFile_manager::AnalysisFileInfo(string & strFile, RECFILE_INFO & recInfo)
{
	int ret = 0;
	char str_finfo[80];
	char file_path[250];
	int ch = 0;
	int  sz_len = strFile.length();
	char sz_recType[8] = {0};
	char sz_tmTime[30] = {0};
	struct  tm recTm;
	string  rec_path;;

	strcpy(str_finfo,strFile.c_str());;
	if(strstr(str_finfo,"ch"))
	{
		sscanf(str_finfo,"ch%d_NOR_%04d%02d%02d_%02d%02d%02d",&ch,
			&recTm.tm_year,&recTm.tm_mon,&recTm.tm_mday,
			&recTm.tm_hour,&recTm.tm_min,&recTm.tm_sec
			);
	}
	else
	{
		if(strstr(str_finfo,"NOR"))
		{
			sscanf(str_finfo,"NOR_%04d%02d%02d_%02d%02d%02d",
				&recTm.tm_year,&recTm.tm_mon,&recTm.tm_mday,
				&recTm.tm_hour,&recTm.tm_min,&recTm.tm_sec
				);
		}
		else
		{
			sscanf(str_finfo,"%04d%02d%02d_%02d%02d%02d",
				&recTm.tm_year,&recTm.tm_mon,&recTm.tm_mday,
				&recTm.tm_hour,&recTm.tm_min,&recTm.tm_sec
				);
		}
	}

	recTm.tm_year  -= 1900;
	recTm.tm_mon   -= 1;
	recTm.tm_isdst  = 0;
	time_t tm_start = mktime(&recTm);

	recInfo.channel  = ch;
	recInfo.tmStartSec = tm_start;
	recInfo.tmEndSec   = tm_start + 5 * 60;

	m_fCreater.GetPath(F_NOR_REC,rec_path);
	if(!rec_path.empty())
	{
		sprintf(file_path,"%s%s",rec_path.c_str(),strFile.c_str());
		recInfo.length  = get_file_sie(file_path);
	}
	else
	{
		recInfo.length = 0;
	}

	if(strstr(str_finfo,"NOR"))
	{
		recInfo.fileType = F_NOR_REC;
	}
	else if(strstr(str_finfo,"EVT"))
	{
		recInfo.fileType = F_EVT_REC;
	}
	else
	{
		recInfo.fileType = F_EVT_REC;
	}

	return ret;
}

int CFile_manager::AnalysisFileList(vector<string> & vec_recFile)
{
	int ret = 0;
	RECFILE_INFO  fInfo;

	int f_num = (int)vec_recFile.size();
	int i = 0;

	MAP_RECFILE_INFO::iterator it ;

	for(i = 0; i < f_num; i++)
	{
		AnalysisFileInfo(vec_recFile[i],fInfo);
		m_map_fileInfo.insert(MAP_RECFILE_INFO::value_type((uint32_t)fInfo.tmStartSec,fInfo));
	}

	return ret;
}

int CFile_manager::CreateThumbnail(char * recName)
{
	int ret = 0;

	return ret;
}

int CFile_manager::DelThumbnail(char * recName)
{
	bool bRet = 0;

	char pic_path[128] = {0}; //缩略图路径

	sprintf(pic_path,"%s%s",m_fCreater.GetDir_mount(),recName);

	bRet = DeleteFile(pic_path);

	return bRet;
}

int CFile_manager::GetDiskInfo()
{
	uint64_t i64TotalBytes = 0;
#ifdef _WIN32
	uint64_t i64FreeByteToCaller = 0;
	uint64_t i64FreeBytes = 0;

	BOOL bRet = GetDiskFreeSpaceEx(m_dev,
		(PULARGE_INTEGER)&i64FreeByteToCaller,
		(PULARGE_INTEGER)&i64TotalBytes,
		(PULARGE_INTEGER)&i64FreeBytes);
	if(!bRet)
	{
		TRACE_ERR("Cannot get disk free space.\n");
		return ERR_DATA_SIZE;
	}
	m_total_space_MB = i64TotalBytes >> 20;
#else
// 	struct statvfs disk_statfs;
// 	if( statvfs(m_dev, &disk_statfs) == -1 )
// 	{
//		return 16;
// 	}
//	i64TotalBytes = (uint64_t)disk_statfs.f_bsize * (uint64_t)disk_statfs.f_blocks;
//	m_total_space_MB = i64TotalBytes>>20;

	int fd = open(m_dev,O_RDONLY);
	if(fd >= 0)
	{
	    int ret = ioctl(fd,BLKGETSIZE,&i64TotalBytes);
        close(fd);
		m_total_space_MB = i64TotalBytes * 512 >> 20;
		printf("Get dev %s secs %lld total space %d MB.\n", m_dev,i64TotalBytes,m_total_space_MB);
	}
	else
	{
		m_total_space_MB = 32 * 1024;
	}

#endif
	return m_total_space_MB;
}

int CFile_manager::GetFilePath(char * fileName, FILE_INFO & fInfo)
{
	int ret = 0;
	int fileType = F_NOR_REC;

	ret = m_fCreater.GetFilePath(fileName,F_NOR_REC,fInfo.tmStart,fInfo.channel);

	return ret;
}
